package com.meis.widget.xiaohongshu;

import com.ryan.ohos.extension.ViewConfiguration;
import cs.help.tool.Log;
import ohos.agp.components.*;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;


/**
 * Created by wenshi on 2019/3/6.
 * Description
 */
public class CoordinatorRecyclerView extends ListContainer
        implements Component.BindStateChangedListener, Component.TouchEventListener {
    private int mTouchSlop = -1;
    private VelocityDetector mVelocityTracker;
    // 是否重新测量用于改变RecyclerView的高度
    private boolean mIsAgainMeasure = true;
    // 是否展开 默认为true
    private boolean mIsExpand = true;
    // 父类最大的滚动区域 = 裁剪控件的高度
    private int mMaxParentScrollRange;
    // 父控件在y方向滚动的距离
    private int mCurrentParenScrollY = 0;
    // 最后RawY坐标
    private float mLastRawY = 0;
    private float mDeltaRawY = 0;
    // 回调接口
    private OnCoordinatorListener mListener;
    // 兼容点击事件失效
    private float mDownRawY = 0;

    public CoordinatorRecyclerView(@NotNull Context context) {
        this(context, null);
    }

    public CoordinatorRecyclerView(@NotNull Context context, @Nullable AttrSet attrs) {
        this(context, attrs, "");
    }

    public CoordinatorRecyclerView(@NotNull Context context, @Nullable AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);
        mVelocityTracker = VelocityDetector.obtainInstance();
        mMaxParentScrollRange = DisplayManager.getInstance().getDefaultDisplay(context)
                .orElse(null).getRealAttributes().width;
        setBindStateChangedListener(this);
        setTouchEventListener(this);
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent e) {
        if (mListener == null) {
            return false;
        }
        if (mTouchSlop < 0) {
            mTouchSlop = ViewConfiguration.getTouchSlop();
        }
        switch (e.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                // 重置数据
                resetData();
                mLastRawY = e.getPointerScreenPosition(e.getIndex()).getY();
                mDownRawY = e.getPointerScreenPosition(e.getIndex()).getY();
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityDetector.obtainInstance();
                } else {
                    mVelocityTracker.clear();
                }
                mVelocityTracker.addEvent(e);
                break;

            case TouchEvent.POINT_MOVE:
                float y = e.getPointerPosition(e.getIndex()).getY();
                measureRecyclerHeight(y);
                int listAllheight = 0;
                if (getItemProvider() instanceof CoordinatorAdapter) {
                    listAllheight = ((CoordinatorAdapter) getItemProvider()).getAllLength();
                }
                if (y < 0 || getScrollValue(AXIS_Y) == 0) {
                    mDeltaRawY += mLastRawY - e.getPointerScreenPosition(e.getIndex()).getY();
                    mListener.onScroll(y, mDeltaRawY, mMaxParentScrollRange);
                }
                if(getScrollValue(AXIS_Y)+getWidth()>=listAllheight){
                    mDeltaRawY += mLastRawY - e.getPointerScreenPosition(e.getIndex()).getY();
                    mListener.onScroll(-1, mDeltaRawY, mMaxParentScrollRange);
                }
                mVelocityTracker.addEvent(e);
                mLastRawY = e.getPointerScreenPosition(e.getIndex()).getY();
                break;
            case TouchEvent.CANCEL:
            case TouchEvent.PRIMARY_POINT_UP:
                // 重置数据
                resetData();
                mLastRawY = 0;
                // 处理滑动速度
                mVelocityTracker.addEvent(e);
                mVelocityTracker.calculateCurrentVelocity(1000);

                int velocityY = (int) Math.abs(mVelocityTracker.getVerticalVelocity());
                mListener.onFiling(mDeltaRawY > 0 ? -velocityY : velocityY);
                mDeltaRawY = 0;
                // 处理子view点击事件失效
                final int yDiff = (int) Math.abs(e.getPointerScreenPosition(e.getIndex()).getY() - mDownRawY);
                if (yDiff < mTouchSlop) {
                    mListener.handlerInvalidClick((int) e.getPointerScreenPosition(e.getIndex()).getX(),
                            (int) e.getPointerScreenPosition(e.getIndex()).getY());
                }
                break;
        }
        return true;
    }

    private void resetData() {
        // 重置数据
        mIsAgainMeasure = true;
        // 展开为0 不然会最大高度
        mCurrentParenScrollY = mIsExpand ? 0 : mMaxParentScrollRange;
    }

    public void setMaxParentScrollRange(int maxParentScrollRange) {
        mMaxParentScrollRange = maxParentScrollRange;
    }

    private void measureRecyclerHeight(float y) {
        if (y <= 0 && mIsAgainMeasure) {
            if (getHeight() < mMaxParentScrollRange && mIsExpand) {
                mIsAgainMeasure = false;
                getLayoutConfig().height = getHeight() + mMaxParentScrollRange;
                postLayout();
            }
        }
    }

    // 重置高度
    public void resetRecyclerHeight() {
        if (getHeight() > mMaxParentScrollRange && mIsExpand && mIsAgainMeasure) {
            getLayoutConfig().height = getHeight() - mMaxParentScrollRange;
            postLayout();

            getItemProvider().notifyDataChanged();
        }
    }

    @Override
    public void onComponentBoundToWindow(Component component) {

    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        if (mVelocityTracker != null) {
            mVelocityTracker.clear();
            mVelocityTracker = null;
        }
    }

    // 设置是否展开
    public void setExpand(boolean expand) {
        mIsExpand = expand;
    }

    // 设置当前滚动的y轴距离
    public void setCurrentParenScrollY(int currentParenScrollY) {
        mCurrentParenScrollY = currentParenScrollY;
    }

    public int getmCurrentParenScrollY() {
        return mCurrentParenScrollY;
    }

    public interface OnCoordinatorListener {

        void onScroll(float y, float deltaY, int maxParentScrollRange);

        void onFiling(int velocityY);
        // 处理子view的点击失效
        void handlerInvalidClick(int rawX, int rawY);
    }

    public void setOnCoordinatorListener(OnCoordinatorListener listener) {
        this.mListener = listener;
    }

    public static abstract class CoordinatorAdapter extends BaseItemProvider {
        public abstract int getAllLength();
    }
}
